home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
intser.exe
/
INTSER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-19
|
15KB
|
534 lines
/************************************************************************/
/* */
/* Minimal Function, All C interrupt serial routine */
/* */
/* Supports buffered input, output */
/* */
/* */
/************************************************************************/
/* */
/* This code is donated to the public domain */
/* */
/************************************************************************/
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
/************************************************************************/
/* */
/* The following callable subroutines are in this library */
/* */
/************************************************************************/
int ser_int_icount(); /* Count of chars in input buffer */
int ser_int_ocount(); /* Count of chars in output buffer */
int ser_int_ofree(); /* Count of free space in output buffer */
void ser_int_iflush(); /* Flushes input buffer */
void ser_int_init(); /* Initializes interrupt handler */
void ser_int_term(); /* Terminates interrupt handler */
void ser_int_putc(); /* Sends a character */
int ser_int_getc(); /* Gets a character */
void ser_int_puts(); /* Sends a string */
void ser_int_break(); /* Sends a break signal */
/************************************************************************/
/* Definitions of the 8250's registers */
/************************************************************************/
unsigned ser_vect; /* Interrupt vector to use */
unsigned DataPort; /* Data register */
unsigned IER; /* Interrupt enable register */
unsigned IIR; /* Interrupt ID register */
unsigned LCR; /* Line control register */
unsigned MControl; /* Modem control register */
unsigned LStatus; /* Line Status */
unsigned MStatus; /* Modem status */
unsigned IntControl; /* For 8259 interrupt controller */
unsigned EnableIRQ4; /* Enable interrupt 4 */
unsigned DisableIRQ4; /* Disable interrupt 4 */
unsigned RS8259;
unsigned EOI;
unsigned TxReady; /* Transmit buffer empty */
static (_interrupt _far *old_vect)();
/* The previous interrupt vector. */
/************************************************************************/
/* Definitions of the interrupt enable register */
/************************************************************************/
#define IER_RX 0x01 /* Enable Data Ready interrupts */
#define IER_TX 0x02 /* Enable Transmit Empty Interrupts */
#define IER_LS 0x04 /* Enable line status interrupts */
#define IER_MS 0x08 /* Enable modem status interrupts */
/************************************************************************/
/* Definitions of the interrupt ID register */
/************************************************************************/
#define IIR_IPending 0x01 /* Interrupt is pending */
#define IIR_Mask 0x06 /* Mask to get Interrupt type */
#define IIR_MS 0x00 /* Modem status interrupt */
#define IIR_TX 0x02 /* Transmit empty interrupt */
#define IIR_RX 0x04 /* Data available interrupt */
#define IIR_LS 0x06 /* Line status interrupt */
#define BUFSIZE 512 /* How many characters in the buffer? */
#define XOFF_SIZE 384 /* How full do we get before XOFFing */
#define XON_SIZE 128 /* How empty to we get before XONing */
#define XOFF 19 /* value of the XOFF character */
#define XON 17 /* value of the XON character */
/************************************************************************/
/* */
/* Definitions for the input buffer. */
/* */
/* We make it a 'far' array so as not to eat up valuable data */
/* space in the small and medium models. */
/* */
/* The buffers are simple circular buffers, where there is */
/* one pointer to fill the buffer and another to empty it. */
/* A count variable keeps track of the size of the buffer */
/* (although it could be determined by computing */
/* (fill-empty)%BUFSIZE). */
/* */
/************************************************************************/
static unsigned char far in_buf[BUFSIZE];
static int in_fill =0; /* Where to place the next char */
static int in_empty =0; /* Where to get the next char */
static int in_count =0; /* How much data is in buffer */
static int xoff_sent =0; /* Did we send an XOFF? */
/************************************************************************/
/* */
/* Definitions for the output buffer */
/* */
/************************************************************************/
static unsigned char far out_buf[BUFSIZE];
static int out_fill =0;
static int out_empty =0;
static int out_count =0;
static int tx_off =1; /* These means the interrupts */
/* for the transmitter are now */
/* off (since we have nothing */
/* to send right now). */
/************************************************************************/
/* */
/* ser_int_icount: Return the number of bytes in the input */
/* buffer. 0 means no data available. */
/* */
/************************************************************************/
int ser_int_icount()
{
return(in_count);
}
/************************************************************************/
/* */
/* ser_int_ocount: Returns the number of bytes in the output */
/* buffer. This information is useful if you */
/* are uploading a large block of data and do */
/* not want to hand this library data quicker */
/* than it can be transmitted. E.g., */
/* */
/* while (more data) */
/* { */
/* while (ser_int_ocount()) */
/* ; */
/* send_data(); */
/* } */
/* */
/************************************************************************/
int ser_int_ocount()
{
return(out_count);
}
/************************************************************************/
/* */
/* ser_int_ofree: Returns the amount of free space left in */
/* the output buffer. Useful in preventing */
/* hanging in ser_int_putc while sending a */
/* a large block of data. E.g., */
/* */
/* while (more_data) */
/* { */
/* while (ser_int_ofree() == 0) */
/* do_something_else(); */
/* ser_int_putc(data); */
/* } */
/* */
/************************************************************************/
int ser_int_ofree()
{
return(BUFSIZE-out_count);
}
/************************************************************************/
/* */
/* ser_int_iflush: Throw away any data in the input buffer. */
/* Note that if a character arrives just as */
/* this subroutine is returning, there will */
/* be data in the input buffer upon return. */
/* Thus, you cannot rely upon the buffer */
/* being empty (for whatever reason). */
/* */
/************************************************************************/
void ser_int_iflush()
{
_disable();
/*****************************************/
in_fill = 0;
in_empty = 0;
in_count = 0;
/*****************************************/
_enable();
}
/************************************************************************/
/* */
/* int_handler: This routine catches the serial port */
/* interrupts, and performs accordingly. */
/* */
/************************************************************************/
static void interrupt far int_handler()
{
int ax;
static int send_now = 0;
/* While there is more work to do... */
while (0 == ((ax = inp(IIR)) & IIR_IPending))
{
switch (ax & IIR_Mask)
{
case IIR_RX: /* New data has arrived */
ax =inp(DataPort);
if (in_count != BUFSIZE)
{
in_buf[in_fill] = (unsigned char) ax;
in_fill = (in_fill+1) & (BUFSIZE-1);
in_count++;
/* Check for the buffer filling up... */
if ((in_count == XOFF_SIZE) && (!xoff_sent))
{